/* *****************************************************************************
 * JFab (http://code.google.com/p/jfab)
 * Copyright (c) 2011 JFab.org
 * Admin jfab@jeffreythompson.net
 *
 * See the file "LICENSE.txt" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * *****************************************************************************/


package org.jfab.core;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;

import org.jfab.core.io.CGSpecWriter;
import org.jfab.core.model.CGSpec;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;


/**
 * Provides an application to reverse engineer Java source files.
 *
 * <ol>
 * <li>Read filenames in a directory, or from a file</li>
 * <li>Create a CGSpec</li>
 * <li>For each file in a directory</li>
 * <li>Read file contents</li>
 * <li>Add CGObjects to a CGSpec</li>
 * <li>Write CGSpec to a file</li>
 * </ol>
 */
public class ReverseEngineerMain
{
    /**
     * Application method.
     *
     * @param   args  Application arguments.
     *
     * @throws  ParseException  if there is a parse problem.
     * @throws  IOException     if there is an I/O problem.
     */
    public static void main(String[] args) throws ParseException, IOException
    {
        Options options = createOptions();
        CommandLineParser parser = new PosixParser();
        CommandLine commandLine = parser.parse(options, args);

        if (commandLine.hasOption('h'))
        {
            printHelp(options);
        }
        else if (commandLine.hasOption('d'))
        {
            ReverseEngineer reverseEngineer = new JavaReverseEngineer();
            File inputDirectory = new File(determineInputDirectory(
                        commandLine));
            System.out.println("inputDirectory = "
                + inputDirectory.getAbsolutePath());

            CGSpec cgSpec = reverseEngineer.reverseEngineerCodeFilesInDirectory(
                    inputDirectory);
            File outputFile = new File("CodeGenerator.xml");
            CGSpecWriter cgSpecWriter = new CGSpecWriter();
            FileWriter writer = new FileWriter(outputFile);
            cgSpecWriter.write(writer, cgSpec);
            writer.flush();
            writer.close();
        }
        else
        {
            throw new IllegalArgumentException("Option d must be specified.");
        }
    }

    /**
     * @return  application command line options.
     */
    private static Options createOptions()
    {
        Options answer = new Options();

        Option help = new Option("h", "print this message");

        OptionBuilder.withArgName("directory");
        OptionBuilder.hasArg();
        OptionBuilder.withDescription("input directory");

        Option directory = OptionBuilder.create("d");

        answer.addOption(help);
        answer.addOption(directory);

        return answer;
    }

    /**
     * @param   commandLine  Command line.
     *
     * @return  output directory.
     */
    private static String determineInputDirectory(CommandLine commandLine)
    {
        String answer = "";

        char option = 'd';

        if (commandLine.hasOption(option))
        {
            answer = commandLine.getOptionValue(option);
        }

        return answer;
    }

    /**
     * Print the help text.
     *
     * @param  options  Command line options.
     */
    private static void printHelp(Options options)
    {
        // Automatically generate the help statement.
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("java [-cp <classpath>] org.jfab.core.JFabber",
            options);
    }
}
